package impl

import (
	"context"
	"errors"

	"gitee.com/hexug/devcloud/mcenter/apps/policy"
	"gitee.com/hexug/devcloud/mcenter/apps/role"
	"gitee.com/hexug/devcloud/mcenter/apps/user"
	"gitee.com/hexug/devcloud/mcenter/common/logger"
	"gitee.com/hexug/devcloud/mcenter/common/validate"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
)

func (i *implServer) CreatePolicy(ctx context.Context, in *policy.CreatePolicyRequest) (*policy.Policy, error) {
	if err := validate.V().Struct(in); err != nil {
		logger.L().Error(err.Error())
		return nil, err
	}
	//校验user_id
	durbid := user.NewDetailUserRequestById(in.UserId)
	_, err := i.user.DetailUser(ctx, durbid)
	if err != nil {
		logger.L().Error(err.Error())
		return nil, errors.New("未找到对应合法用户")
	}
	//校验role_id
	drrbid := role.NewDetailRoleRequestByID(in.RoleId)
	if _, err := i.RSvc.DetailRole(ctx, drrbid); err != nil {
		logger.L().Error(err.Error())
		return nil, errors.New("未找到对应合法角色")
	}
	plc := policy.NewPolicy(in)
	if _, err := i.Col.InsertOne(ctx, plc); err != nil {
		logger.L().Error(err.Error())
		return nil, err
	}
	return plc, nil
}

func (i *implServer) QueryPolicy(ctx context.Context, in *policy.QueryPolicyRequest) (*policy.PolicySet, error) {
	if err := validate.V().Struct(in); err != nil {
		logger.L().Error(err.Error())
		return nil, err
	}
	//防止过度获取
	if in.PageSize <= 0 || in.PageSize > 30 {
		in.PageSize = 5
	}
	if in.PageNumber <= 0 || in.PageNumber > 10 {
		in.PageNumber = 1
	}
	// fmt.Println(in)
	filter := bson.M{}
	if in.IsValidate {
		filter["user_id"] = in.UserId
		filter["namespces"] = in.Namespace
	} else {
		if in.UserId != "" {
			filter["user_id"] = in.UserId
		}
		if in.Namespace != "" {
			filter["namespces"] = in.Namespace
		}
	}
	//按创建时间倒排
	opt := options.Find().
		SetLimit(in.PageSize).
		SetSkip((in.PageNumber - 1) * in.PageSize).
		SetSort(bson.D{{Key: "created_at", Value: -1}}) //按创建时间倒序取出
	cursor, err := i.Col.Find(ctx, filter, opt)
	if err != nil {
		logger.L().Error(err.Error())
		return nil, err
	}
	d := policy.NewPolicySet()
	if err := cursor.All(ctx, &d.Items); err != nil {
		logger.L().Error(err.Error())
		return nil, err
	}
	count, err := i.Col.CountDocuments(ctx, filter)
	if err != nil {
		logger.L().Error(err.Error())
		return nil, err
	}
	d.Total = count
	if in.WithRole {
		for _, p := range d.Items {
			drr := role.NewDetailRoleRequestByID(p.Spec.RoleId)
			r, err := i.RSvc.DetailRole(ctx, drr)
			if err != nil {
				logger.L().Error(err.Error(), p.Spec.RoleId)
				continue
			}
			p.Role = r
		}
	}
	return d, nil
}

func (i *implServer) DetailPolicy(ctx context.Context, in *policy.DetailPolicyRequest) (*policy.Policy, error) {
	if err := validate.V().Struct(in); err != nil {
		logger.L().Error(err.Error())
		return nil, err
	}
	filter := bson.M{"_id": in.PolicyId}
	p := policy.New()
	res := i.Col.FindOne(ctx, filter)
	if res.Err() != nil {
		logger.L().Error(res.Err().Error())
		return nil, res.Err()
	}
	if err := res.Decode(p); err != nil {
		return nil, err
	}
	return p, nil
}
